console.log(+0 === -0); //true
console.log(NaN === NaN); // false

console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true


//Object.assign方法实行的是浅拷贝，而不是深拷贝
var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 1 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); // {a:1, b:2, c:3}

//ES6一共有5种方法可以遍历对象的属性。
//
// （1）for...in
//
// for...in循环遍历对象自身的和继承的可枚举属性（不含Symbol属性）。
//
// （2）Object.keys(obj)
//
// Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含Symbol属性）。
//
// （3）Object.getOwnPropertyNames(obj)
//
// Object.getOwnPropertyNames返回一个数组，包含对象自身的所有属性（不含Symbol属性，但是包括不可枚举属性）。
//
// （4）Object.getOwnPropertySymbols(obj)
//
// Object.getOwnPropertySymbols返回一个数组，包含对象自身的所有Symbol属性。
//
// （5）Reflect.ownKeys(obj)
//
// Reflect.ownKeys返回一个数组，包含对象自身的所有属性，不管是属性名是Symbol或字符串，也不管是否可枚举。
//
// 以上的5种方法遍历对象的属性，都遵守同样的属性遍历的次序规则。
//
// 首先遍历所有属性名为数值的属性，按照数字排序。
// 其次遍历所有属性名为字符串的属性，按照生成时间排序。
// 最后遍历所有属性名为Symbol值的属性，按照生成时间排序。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]


var obj = { foo: 'bar', baz: 42 };
console.log(Object.keys(obj));

//Object.values 只返回对象自身的可遍历属性
console.log(Object.values(obj)); // ["bar", 42]

//Object.create方法的第二个参数添加的对象属性（属性p），如果不显式声明，默认是不可遍历的，
// 因为p的属性描述对象的enumerable默认是false，Object.values不会返回这个属性
var obj1 = Object.create({}, {p: {value: 42}});
console.log(Object.values(obj1)); // []

var obj2 = Object.create({}, {p:
        {
            value: 42,
            enumerable: true
        }
});
console.log(Object.values(obj2)); // [42]

var obj3 = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj3));  // [ ["foo", "bar"], ["baz", 42] ]


